//
//  GCHelper.m
//  lnnipad
//
//  Created by Wu Wang on 11-11-22.+++++++++++++++++++++++++++++++++++++++++
//  Copyright (c) 2011年 __MyCompanyName__. All rights reserved.
//

#import "RootViewController.h"
#import "../libs/cocos2dx/platform/ios/EAGLView.h"
#import "GCHelper.h"

#pragma mark export code

static GCHelper *g_shareHelper = nil;
static UIViewController *tempVC = nil;
const NSString *strCatlog;

void GCInit()
{
    [[GCHelper ShareInstance] AuthenticateLocalUser];
}

void GCShowLeaderBoard()
{
    [[GCHelper ShareInstance] ShowLeaderboard];
}

void GCReportGameScore(unsigned long score)
{
    [[GCHelper ShareInstance] ReportScore:score :@"hellohah"];
}

void GCFindPlayer(int minPlayer, int maxPlayer, CGCMatchDelegate *pMatchDelegate)
{
    tempVC = [[[RootViewController alloc] init] autorelease];
    
    
    [[EAGLView sharedEGLView] addSubview:tempVC.view];
    

    [[GCHelper ShareInstance] FindMatchWithMinPlayers:minPlayer maxPlayers:maxPlayer viewController:tempVC delegate:pMatchDelegate];
}

bool GCSendMatchData(const void *data, unsigned long dataLen)
{
    NSError *sendError;
    
    BOOL sucess = [[GCHelper ShareInstance].m_pMatch sendDataToAllPlayers:[NSData dataWithBytes:data length:dataLen] withDataMode:GKMatchSendDataReliable error:&sendError];
    
    if(!sucess)
    {
        NSLog(@"发送数据失败");
        return false;
    }
    
    return true;
}

bool GCIsAuthenticated()
{
    GKLocalPlayer *localPlayer = [GKLocalPlayer localPlayer];
    
    if(YES == [localPlayer isAuthenticated])
    {
        return true;
    }
    return false;
}

bool GCGetLocalPlayerID(char *outID)
{
    
    GKLocalPlayer *player = [GKLocalPlayer localPlayer];
    
    if([player isAuthenticated] == YES)
    {
        char szID[ID_MAX_LENGTH];
        NSUInteger len;
        NSRange range = NSMakeRange(0, 32);
        
        [[player playerID] getBytes:szID maxLength:32 usedLength:&len encoding:NSASCIIStringEncoding options:0 range:range remainingRange:NULL];
        
        strcpy(outID, szID);
        return true;
    }

    return false;
}

bool GCGetDeviceID(char *outID)
{
    UIDevice *device = [UIDevice currentDevice];
    
    char szID[ID_MAX_LENGTH];
    
    NSUInteger len;
    NSRange range = NSMakeRange(0, 32);
    [[device uniqueIdentifier] getBytes:szID maxLength:32 usedLength:&len encoding:NSASCIIStringEncoding options:0 range:range remainingRange:NULL];
    strcpy(outID, szID);
    return true;
}

#pragma mark block code

void (^GetLocalPlayerFriendsID)(void) = ^
{
    GKLocalPlayer *localPlayer = [GKLocalPlayer localPlayer];
    
    if([localPlayer isAuthenticated] == NO)
    {
        NSLog(@"当前账户没有登陆");
        return;
    }
    
    NSLog(@"正在获取好友ID……");
    [localPlayer loadFriendsWithCompletionHandler:^(NSArray *friends, NSError *error)
     {
         if(friends != nil)
         {
             NSLog(@"加载好友列表成功！");
             
             unsigned long counter = 1;
             
             for(NSString *friendID in friends)
             {
                 NSLog(@"好友序号 %lu 的ID为：%@", counter, friendID);
                 counter++;
             }
         }
         
         if(error != nil)
         {
             NSLog(@"获取好友列表发生错误，错误：%@", error);
         }
     }];
};

void (^GetLocalPlayerFriendsDetails)(void) = ^
{
    GKLocalPlayer *player = [GKLocalPlayer  localPlayer];
    
    if([player isAuthenticated] == NO)
    {
        NSLog(@"当前账户没有登陆");
        return;
    }
    
    if([[player friends] count] == 0)
    {
        NSLog(@"当前用户没有好友");
        return;
    }
    
    NSLog(@"正在加载用户朋友列表……");
    
    [GKPlayer loadPlayersForIdentifiers:[player friends] withCompletionHandler:^(NSArray *players, NSError *error)
     {
        if(players != nil)
        {
            NSLog(@"成功获取好友列表");
            for(GKPlayer *curPlayer in players)
            {
                NSLog(@"%@", curPlayer);
            }
        }
         
        if(error != nil)
        {
            NSLog(@"获取好友列表发生错误，错误：%@", error);
        }
     }];
};

void (^GetLocalPlayerFriends)(void) = ^
{
    GKLocalPlayer *localPlayer = [GKLocalPlayer localPlayer];
    
    if([localPlayer isAuthenticated] == NO)
    {
        NSLog(@"当前账户没有登陆");
        return;
    }
    
    NSLog(@"正在获取好友信息……");
    [localPlayer loadFriendsWithCompletionHandler:^(NSArray *friends, NSError *error)
     {
         if(friends != nil)
         {
             NSLog(@"加载好友列表成功！");
             
             dispatch_queue_t concurQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
             dispatch_async(concurQueue, GetLocalPlayerFriendsDetails);
        }
         
         if(error != nil)
         {
             NSLog(@"获取好友列表发生错误，错误：%@", error);
         }
     }];

};

void (^GetLocalPlayerInfo)(void) = ^
{
    GKLocalPlayer *player = [GKLocalPlayer localPlayer];
    
    if([player isAuthenticated] == YES)
    {
        NSLog(@"用户ID ＝ %@", [player playerID]);
        NSLog(@"用户别名 ＝ %@", [player alias]);
    }
    
    //GetLocalPlayerFriends();
    
};


@implementation GCHelper

@synthesize m_bGCAvailable;
@synthesize m_pMatchViewController;
@synthesize m_pMatch;
@synthesize m_dicPlayers;
//@synthesize m_delegate;

#pragma mark User functions 

+ (GCHelper *)ShareInstance
{
    if(!g_shareHelper)
    {
        g_shareHelper = [[GCHelper alloc] init];
    }
    
    return g_shareHelper;
}


- (void)AuthenticateLocalUser
{
    
    if (!m_bGCAvailable) return;
    
    dispatch_queue_t concurQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    
    dispatch_async(concurQueue, ^(void)
    {
        GKLocalPlayer *localPlayer = [GKLocalPlayer localPlayer];
        
        if([localPlayer isAuthenticated] == NO)
        {
            NSLog(@"用户正在登陆……");
            [localPlayer authenticateWithCompletionHandler:^(NSError *error)
            {
                if(error == nil)
                {
                    NSLog(@"用户成功登陆");
                    dispatch_async(concurQueue, GetLocalPlayerInfo);
                }
                else
                {
                    NSLog(@"用户登陆失败");
                }
            }];
        }
        else
        {
            NSLog(@"用户已经登陆!");
            dispatch_async(concurQueue, GetLocalPlayerInfo);
        }
    });
    
}

#pragma mark User functions Leaderboard

- (void)ShowLeaderboard
{
    
    tempVC = [[[RootViewController alloc] init] autorelease];
    
    GKLeaderboardViewController *pBoard = [[[GKLeaderboardViewController alloc] init] autorelease];
    
    [pBoard setCategory:@"hellohah"];
    if(nil != pBoard)
    {
        pBoard.leaderboardDelegate = self;
        [[EAGLView sharedEGLView] addSubview:tempVC.view];
        [tempVC presentModalViewController:pBoard animated:YES];
    }
    [self GetCenterScore];
}

- (BOOL)ReportScore:(int64_t)paramSocre :(NSString *)paramLeaderboard
{
    __block BOOL result = NO;
    
    GKLocalPlayer *localPlayer = [GKLocalPlayer localPlayer];
    
    if([localPlayer isAuthenticated] == NO)
    {
        NSLog(@"未登陆账户，无法发送分数");
        return NO;
    }
    
    GKScore *score = [[[GKScore alloc] initWithCategory:paramLeaderboard] autorelease];
    
    score.value = (int64_t)paramSocre;
    
    NSLog(@"开始上传分数……");
    
    [score reportScoreWithCompletionHandler:^(NSError *error)
     {
         if(error != nil)
         {
             NSLog(@"上传分数失败，错误：%@", error);
         }
         else
         {
             NSLog(@"上传分数成功!");
             result = YES;
         }
     }];
    
    return result;
}

- (void)GetCenterScore
{
    GKLeaderboard *pBoard = [[[GKLeaderboard alloc] init] autorelease];
    [pBoard setCategory:@"hellohah"];
    [pBoard loadScoresWithCompletionHandler:^(NSArray *scores, NSError *error)
     {
        if(scores != nil)
        {
            for(GKScore *score in scores)
            {
                NSLog(@"%@", score);
            }
        }
         
        if(error != nil)
        {
            NSLog(@"获取分数失败 错误:");
        }
     }];
}

- (void)FindMatchWithMinPlayers:(int)minPlayers maxPlayers:(int)maxPlayers viewController:(UIViewController *)viewController delegate:(CGCMatchDelegate *)theDelegate
{
    
    if (!m_bGCAvailable) return;
    
    m_bMatchStarted = NO;
    self.m_pMatch = nil;
    self.m_pMatchViewController = viewController;
    m_delegate = theDelegate; 
    
    [m_pMatchViewController dismissModalViewControllerAnimated:NO];

    [GKMatchmaker sharedMatchmaker].inviteHandler = ^(GKInvite *acceptedInvite, NSArray *playersToInvite)
    {
        if(acceptedInvite != nil)
        {
            NSLog(@"一个比赛邀请正在进行……");
            
            GKMatchmakerViewController *mmvc = [[[GKMatchmakerViewController alloc] initWithInvite:acceptedInvite] autorelease];
            
            mmvc.matchmakerDelegate = self;
            
            [m_pMatchViewController presentModalViewController:mmvc animated:YES];
        }
        else if(playersToInvite != nil)
        {
            GKMatchRequest *request = [[[GKMatchRequest alloc] init] autorelease]; 
            request.minPlayers = minPlayers;     
            request.maxPlayers = maxPlayers;
            request.playersToInvite = playersToInvite;
            
            GKMatchmakerViewController *mmvc = [[[GKMatchmakerViewController alloc] initWithMatchRequest:request] autorelease];
            
            mmvc.matchmakerDelegate = self;
            
            [m_pMatchViewController presentModalViewController:mmvc animated:YES];
        }
    };
    

    GKMatchRequest *request = [[[GKMatchRequest alloc] init] autorelease]; 
    request.minPlayers = minPlayers;     
    request.maxPlayers = maxPlayers;
        
    GKMatchmakerViewController *mmvc = [[[GKMatchmakerViewController alloc] initWithMatchRequest:request] autorelease];
        
    mmvc.matchmakerDelegate = self;
        
    [m_pMatchViewController presentModalViewController:mmvc animated:YES];

}

- (void)LookupMatchPlayers
{
    NSLog(@"正在查找 %d 个玩家……", m_pMatch.playerIDs.count);
    
    [GKPlayer loadPlayersForIdentifiers:m_pMatch.playerIDs withCompletionHandler:^(NSArray *players, NSError *error)
     {
         if(nil != error)
         {
             NSLog(@"查找游戏玩家发生错误：%@", error.localizedDescription);
             m_bMatchStarted = NO;
             m_delegate->MatchEnded();
         }
         else
         {
             m_dicPlayers = [NSMutableDictionary dictionaryWithCapacity:players.count];
             for(GKPlayer *player in players)
             {
                 NSLog(@"找到玩家%@", player.alias);
                 [m_dicPlayers setObject:player forKey:player.playerID];
             }
             
             m_bMatchStarted = YES;
             m_delegate->MatchEnded();
         }
         
     }];
}
#pragma mark Internal GameCenterCommon 

- (BOOL)isGameCenterAvailable
{
    // check for presence of GKLocalPlayer API
    Class gcClass = (NSClassFromString(@"GKLocalPlayer"));
    
    // check if the device is running iOS 4.1 or later
    NSString *reqSysVer = @"4.1";
    NSString *currSysVer = [[UIDevice currentDevice] systemVersion];
    BOOL osVersionSupported = ([currSysVer compare:reqSysVer
                                           options:NSNumericSearch] != NSOrderedAscending);
    
    return (gcClass && osVersionSupported);
}

- (id)init
{
    if ((self = [super init])) 
    {
        m_bGCAvailable = [self isGameCenterAvailable];
        if (m_bGCAvailable)
        {
            NSNotificationCenter *nc =
            [NSNotificationCenter defaultCenter];
            [nc addObserver:self
                   selector:@selector(authenticationChanged)
                       name:GKPlayerAuthenticationDidChangeNotificationName
                     object:nil];
        }
    }
    return self;
}

- (void)authenticationChanged {
    
    if ([GKLocalPlayer localPlayer].isAuthenticated && !m_bUserAuthenticated) 
    {
        NSLog(@"用户变化，用户已经变更");
        m_bUserAuthenticated = TRUE;
    } 
    else if (![GKLocalPlayer localPlayer].isAuthenticated && m_bUserAuthenticated) 
    {
        NSLog(@"用户变化，用户没有变更");
        m_bUserAuthenticated = FALSE;
    }
}

#pragma mark GKLeaderboardViewControllerDelegate

- (void)leaderboardViewControllerDidFinish:(GKLeaderboardViewController *)viewController
{
    [tempVC dismissModalViewControllerAnimated:YES];
}

#pragma mark GKMatchmakerViewControllerDelegate

// The user has cancelled matchmaking
- (void)matchmakerViewControllerWasCancelled:(GKMatchmakerViewController *)viewController {
    [m_pMatchViewController dismissModalViewControllerAnimated:YES];
}

// Matchmaking has failed with an error
- (void)matchmakerViewController:(GKMatchmakerViewController *)viewController didFailWithError:(NSError *)error {
    [m_pMatchViewController dismissModalViewControllerAnimated:YES];
    NSLog(@"Error finding match: %@", error.localizedDescription);    
}

// A peer-to-peer match has been found, the game should start
- (void)matchmakerViewController:(GKMatchmakerViewController *)viewController didFindMatch:(GKMatch *)theMatch 
{
    [m_pMatchViewController dismissModalViewControllerAnimated:YES];
    self.m_pMatch = theMatch;
    m_pMatch.delegate = self;
    
    if (!m_bMatchStarted && m_pMatch.expectedPlayerCount == 0)
    {
        NSLog(@"Ready to start match!");
        [self LookupMatchPlayers];
    }
}

#pragma mark GKMatchDelegate

// The match received data sent from the player.
- (void)match:(GKMatch *)theMatch didReceiveData:(NSData *)data fromPlayer:(NSString *)playerID 
{
    
    if (m_pMatch != theMatch) return;
    /*
    [m_delegate Match:theMatch didReceiveData:data fromPlayer:playerID];
     */
    
    char szID[128];
    NSUInteger len;
    NSRange range = NSMakeRange(0, 128);
    
    [playerID getBytes:szID maxLength:128 usedLength:&len encoding:NSASCIIStringEncoding options:0 range:range remainingRange:NULL];
    
    const void *dataBytes = [data bytes];
    unsigned long dataLen = [data length];
    
    m_delegate->ReceivedData(szID, dataBytes, dataLen);
}

// The player state changed (eg. connected or disconnected)
- (void)match:(GKMatch *)theMatch player:(NSString *)playerID didChangeState:(GKPlayerConnectionState)state 
{
    
    if (m_pMatch != theMatch) return;
    
    switch (state) {
        case GKPlayerStateConnected: 
            // handle a new player connection.
            NSLog(@"Player connected!");
            
            if (!m_bMatchStarted && theMatch.expectedPlayerCount == 0) {
                NSLog(@"Ready to start match!");
                [self LookupMatchPlayers];
            }
            
            break; 
        case GKPlayerStateDisconnected:
            // a player just disconnected. 
            NSLog(@"Player disconnected!");
            m_bMatchStarted = NO;
            m_delegate->MatchEnded();
            //[m_delegate MatchEnded];
            break;
    }                 
    
}

// The match was unable to connect with the player due to an error.
- (void)match:(GKMatch *)theMatch connectionWithPlayerFailed:(NSString *)playerID withError:(NSError *)error {
    
    if (m_pMatch != theMatch) return;
    
    NSLog(@"Failed to connect to player with error: %@", error.localizedDescription);
    m_bMatchStarted = NO;
    m_delegate->MatchEnded();
    
    //[m_delegate MatchEnded];
}

// The match was unable to be established with any players due to an error.
- (void)match:(GKMatch *)theMatch didFailWithError:(NSError *)error {
    
    if (m_pMatch != theMatch) return;
    
    NSLog(@"Match failed with error: %@", error.localizedDescription);
    m_bMatchStarted = NO;
    
    m_delegate->MatchEnded();
    //[m_delegate MatchEnded];
}
@end
